package com.kuaidian.util.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.kuaidian.util.SpringContextUtils;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;



public class DynamicDataSource extends AbstractRoutingDataSource{

	private Logger log = Logger.getLogger(this.getClass());
	private Map<Object, Object> _targetDataSources = new HashMap<Object, Object>();
 
	@Autowired
	private SpringContextUtils utils;
	
	@Override     
    protected Object determineCurrentLookupKey() {     
    	
		
        String dataSourceName = DBContextHolder.getDBType();
        if (dataSourceName == null) {
            dataSourceName = "dataSource";
        } else {
            this.selectDataSource(dataSourceName);
            if (dataSourceName.equals("dataSource"))
                dataSourceName = "dataSource";
        }
        log.debug("--------> use datasource " + dataSourceName);
        return dataSourceName;
		
    	
    	//return DBContextHolder.getDBType();     
    }
    
	public void selectDataSource(String dataSourceName){
		
		if (dataSourceName.equals("dataSource")) {
	       DBContextHolder.setDBType("dataSource");
	       return;
		}
		
		 Object obj = this._targetDataSources.get(dataSourceName);
		 if (obj != null) {
			return;
		}else{
			DataSource dataSource = this.getDataSource(dataSourceName);
            if (null != dataSource)
                this.setDataSource(dataSourceName, dataSource);
		}
	}
	
	public Connection getConnection() throws SQLException {

		return determineTargetDataSource().getConnection();
	}
	
	public void init(){
        this.selectDataSource("dataSource");
        this.determineCurrentLookupKey();
		
        
        Connection conn = null;
        HashMap<String, Object> map = null;
        try {
            conn = this.getConnection();
            PreparedStatement ps = conn
                    .prepareStatement("SELECT * FROM t_db ");

            
            ResultSet rs = ps.executeQuery();
            map = new HashMap<String, Object>();
            
            while (rs.next()) {
                map.put("DBS_ID", rs.getString("dbname"));
                map.put("DBS_DriverClassName", rs.getString("driver_class_name"));
                map.put("DBS_URL", rs.getString("url"));
                map.put("DBS_UserName", rs.getString("username"));
                map.put("DBS_Password", rs.getString("pwd"));
				
                String driverClassName = map.get("DBS_DriverClassName").toString();
                String url = map.get("DBS_URL").toString();
                String userName = map.get("DBS_UserName").toString();
                String password = map.get("DBS_Password").toString();
                String dbName =  map.get("DBS_ID").toString();
                DataSource dataSource = this.createDataSource(driverClassName,url, userName, password,dbName);
                
                this.addTargetDataSource(map.get("DBS_ID").toString(), dataSource);
			}
 
            rs.close();
            ps.close();
        } catch (SQLException e) {
            log.error(e);
        } finally {
            try {
            	if (conn != null) {
            		   conn.close();
				}
             
            } catch (SQLException e) {
                log.error(e);
            }
        }
        

        
	}
	
	
    public DataSource getDataSource(String dataSourceName) {
        this.selectDataSource("dataSource");
        this.determineCurrentLookupKey();
        
        
        Connection conn = null;
        HashMap<String, Object> map = null;
        try {
            conn = this.getConnection();
            PreparedStatement ps = conn
                    .prepareStatement("SELECT * FROM t_db WHERE dbname = ?");
            ps.setString(1, dataSourceName);
            
            ResultSet rs = ps.executeQuery();
            map = new HashMap<String, Object>();
            if (rs.next()) {
                map.put("DBS_ID", rs.getString("dbname"));
                map.put("DBS_DriverClassName", rs.getString("driver_class_name"));
                map.put("DBS_URL", rs.getString("url"));
                map.put("DBS_UserName", rs.getString("username"));
                map.put("DBS_Password", rs.getString("pwd"));
            }
            rs.close();
            ps.close();
        } catch (SQLException e) {
            log.error(e);
        } finally {
            try {
                conn.close();
            } catch (SQLException e) {
                log.error(e);
            }
        }
        
        if (null != map) {
            String driverClassName = map.get("DBS_DriverClassName").toString();
            String url = map.get("DBS_URL").toString();
            String userName = map.get("DBS_UserName").toString();
            String password = map.get("DBS_Password").toString();
            String dbName =  map.get("DBS_ID").toString();
            DataSource dataSource = this.createDataSource(driverClassName,url, userName, password,dbName);
            
            return dataSource;
        }
        return null;
        
    }
    
    public DataSource createDataSource(String driverClassName, String url,
            String username, String password,String dbName) {
    	/*
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setTestOnBorrow(true);
        dataSource.setValidationQuery("SELECT 1 FROM DUAL");
        */
    	AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
    	

    	MysqlXADataSource  mysqlXADataSource = new MysqlXADataSource();
    	
    	dataSource.setTestQuery("SELECT 1 FROM DUAL");
    	mysqlXADataSource.setUser(username);
        mysqlXADataSource.setPassword(password);
        mysqlXADataSource.setUrl(url);
        dataSource.setUniqueResourceName(dbName);
        dataSource.setXaDataSource(mysqlXADataSource);
        dataSource.setXaDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
        dataSource.setMaxPoolSize(30);
        mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        return dataSource;
    }
	
    public void setDataSource(String dataSourceName, DataSource dataSource) {
        this.addTargetDataSource(dataSourceName, dataSource);
        DBContextHolder.setDBType(dataSourceName);
    }
	
    public void addTargetDataSource(String key, DataSource dataSource) {
        this._targetDataSources.put(key, dataSource);
        
        
        if (!this._targetDataSources.containsKey("dataSource")) {
        	
        	
        	Object dt = SpringContextUtils.getBean("dataSource");
        	DataSource ds=(DataSource)(dt) ;
        	this._targetDataSources.put("dataSource", ds);
		}
        this.setTargetDataSources(this._targetDataSources);
        this.afterPropertiesSet();
    }
 
    
	
}
